//
//  BBMovieLayer.m
//  xPrexxo
//
//  Created by ben smith on 2/02/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "BBMovieLayer.h"
#import "BBTUIOCursor.h"
#import "BBGestureDecoder.h"
#import <QuartzCore/QuartzCore.h>

@implementation BBMovieLayer

@synthesize gestureDecoder;


-(void)startListening
{
	
	self.gestureDecoder = [[[BBGestureDecoder alloc] init] autorelease];
	self.gestureDecoder.delegate = self;
	[self setValue:[NSNumber numberWithFloat:1.0] forKey:@"BBScale"];
	angularSpeed = 0;
	scale = 1;	
}

-(void)didStartManipulating
{
	[[NSNotificationCenter defaultCenter] postNotificationName:@"BBRegisterMoving" object:self userInfo:nil];
}

-(void)didEndManipulating
{
	CGFloat myScale = [[self valueForKey:@"BBScale"] floatValue];
	if ((speed > 3.0) || (angularSpeed > 0.2)) {
		[self fling];
		return;
	}	
	[[NSNotificationCenter defaultCenter] postNotificationName:@"BBDeregisterMoving" object:self userInfo:nil];
	
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
	if ([[theAnimation valueForKey:@"name"] isEqualToString:@"flinger"]) {
		[self didEndManipulating];
		return;
	}
}

-(void)fling
{
	[CATransaction begin];
	CABasicAnimation *position = [CABasicAnimation animationWithKeyPath:@"position"];
  position.delegate = self; //to get the animationDidStop:finished: message
	position.timingFunction = [self getTimingFunction];
	position.duration = speed/6.0;
  [position setValue:@"flinger" forKey:@"name"];
	[self.superlayer addAnimation:position forKey:@"position"];
	
	CGPoint pos = self.superlayer.position;
	CGFloat flingFactor = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBFlingFactor"];
	pos.x += vector.x * flingFactor;
	pos.y += vector.y * flingFactor;
	self.superlayer.position = pos;	
	
	CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"sublayerTransform"];
 	rotate.timingFunction = [self getTimingFunction];
	rotate.duration = speed/6.0;
 	[self.superlayer addAnimation:rotate forKey:@"sublayerTransform"];
	
	CATransform3D rotateTransform = CATransform3DMakeRotation (angularSpeed * flingFactor, 0.0, 0.0, 1.0);
	self.superlayer.sublayerTransform = CATransform3DConcat(self.superlayer.sublayerTransform, rotateTransform);
	
	angularSpeed = 0;
	vector = NSZeroPoint;
	speed = 0;
	[CATransaction commit];
}


- (CAMediaTimingFunction *)getTimingFunction 
{ 
	CGFloat c1x = 0.0; 
	CGFloat c1y = 0.0; 
	CGFloat c2x = 0.25; 
	CGFloat c2y = 1.0; 
	return [CAMediaTimingFunction functionWithControlPoints:c1x :c1y :c2x :c2y]; 
} 


-(void)finishCursorCycle
{
	[gestureDecoder finishCursorCycle];
	// figure out what the hell happened
	if (gestureDecoder.eventMask == 0) return;
	//	[self removeAllAnimations];
	
	CGPoint localPoint = [self convertPoint:gestureDecoder.centroid fromLayer:self.superlayer.superlayer];
	// now scale it down to unit coords
	float width = [self bounds].size.width;
	float height = [self bounds].size.height;
	
	CGPoint unitCentroid = CGPointMake(localPoint.x/width, localPoint.y/height);
	
	// now we need to calculate a new positional offset to compensate for the change in anchor position
	CGPoint pos = self.position;
	CGPoint anchor = self.anchorPoint;
	anchor.x *= width;
	anchor.y *= height;
	pos.x += localPoint.x - anchor.x;
	pos.y += localPoint.y - anchor.y;
	
	
	//	if (gestureDecoder.eventMask & BBSelectEventMask) [self handleSelect];
	if (gestureDecoder.eventMask & BBDragEventMask) [self handleDrag];
	if (gestureDecoder.eventMask & BBRotateEventMask) [self handleRotate];
	if (gestureDecoder.eventMask & BBRotateEventMask) [self handleScale];
}

-(void)handleRotate
{
	angularSpeed = gestureDecoder.angle - lastAngle;
	lastAngle = gestureDecoder.angle;
	//	angle += gestureDecoder.angle;
	//	CATransform3D totalTransform = self.transform;
	CATransform3D rotate = CATransform3DMakeRotation (gestureDecoder.angle, 0.0, 0.0, 1.0);
	self.superlayer.sublayerTransform = CATransform3DConcat(self.superlayer.sublayerTransform, rotate);
}


-(void)handleScale
{
	//	angle += gestureDecoder.angle;
	//	CATransform3D totalTransform = self.transform;
	CGFloat layerScale = [[self valueForKey:@"BBScale"] floatValue];
	[self setValue:[NSNumber numberWithFloat:(layerScale* gestureDecoder.scale)] forKey:@"BBScale"];
	CATransform3D scale = CATransform3DMakeScale(gestureDecoder.scale, gestureDecoder.scale, 1.0) ;
	self.superlayer.sublayerTransform = CATransform3DConcat(self.superlayer.sublayerTransform, scale);
}

-(void)handleDrag
{

	// now I have 2 matching cursors, it is a drag
	CGPoint dragVector = gestureDecoder.vector;
	
	CGPoint pos = self.superlayer.position;
	pos.x += dragVector.x;
	pos.y += dragVector.y;
	vector = NSPointFromCGPoint(dragVector);
	speed = hypotf(dragVector.x, dragVector.y);
	self.superlayer.position = pos;	
}


- (void) dealloc
{
	[gestureDecoder release];
	[super dealloc];
}


@end
